package manegement;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;

import dao.DBFacade;

import bean.PostBean;

public class PostManager {

	private HashMap<String, CommentManager> commentsOfPosts;
	
	private HashMap<String, MediaManager> mediasOfPosts;
	
	private HashMap<String, PostBean> posts;
	
	
	
	public PostManager(String blogId) {
		posts = new HashMap<String, PostBean>();
		commentsOfPosts = new HashMap<String, CommentManager>();
		mediasOfPosts = new HashMap<String, MediaManager>();
		PostBean post;
		for(Iterator<PostBean> it = DBFacade.getInstance().getPostsByBlog(blogId).iterator(); it.hasNext();){
			post = it.next();
			posts.put(post.getId(), post);
			commentsOfPosts.put(post.getId(), new CommentManager(post.getId()));
			mediasOfPosts.put(post.getId(), new MediaManager(post.getId()));
		}
	}

	//Post Operations
	/**
	 * Creare a new post
	 * @param sessionId
	 * @param blogId
	 * @param title
	 * @param text
	 * @return postId
	 * @throws Exception
	 */
	public String createPost(String owner, String title, String text, String date) throws Exception {
		
		if(title == null || title.trim().equals(""))
			throw new Exception("Invalid title. Title of post must have text.");
		
		
		String id = getNewPostId();
		
		posts.put(id, new PostBean(id, title, text, date, owner));
		
		mediasOfPosts.put(id,new MediaManager(id));
		commentsOfPosts.put(id, new CommentManager(id));
		return id;
	
	}


	/**
	 * Retrieves a post attribute value
	 * 
	 * @param postID
	 * @param attribute
	 *            - Attribute which you wants to know value
	 * @return attribute value
	 * @throws Exception
	 *             - Throwns exceptions if given att is invalid
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public String getPostInformation(String postId, String attribute)
		throws Exception {
		
		attribute.replaceFirst(attribute.substring(0, 1), attribute.substring(0, 1).toUpperCase());
		PostBean post = posts.get(postId);
		try {
			Class postBeanClass = post.getClass();
			
			Method thisMethod = postBeanClass.getMethod("get"
					+ attribute, (Class[]) null);

			Object result = thisMethod.invoke(post,
					(Object[]) null); // we can receive a null
			return result.toString();
		} catch (Exception e) {
			throw new Exception("Invalid attribute.");
		}
	} 
	
	/**
	 * Modifies the information of the post passed as parameter
	 * @param sessionId
	 * 			- Identifier of the session to validate the User logon
	 * @param postId
	 * 			- Identifier of the post modification
	 * @param attribute
	 * 			- Attribute to be modified
	 * @param value
	 * 			- Value that will be inserted
	 * @throws Exception
	 */
	public void changePostInformation(String postId,
			String attribute, String value) throws Exception {
		
		PostBean post = posts.get(postId);
		if(post == null)
			throw new Exception("Invalid post id.");
		if(attribute.endsWith("title")){
			if(value == null || value.trim().equals(""))
				throw new Exception("Invalid title. Title of post must have text.");
			post.setTitle(value);

		} else if(attribute.endsWith("text")){
			post.setContent(value);
		}
		throw new Exception("Invalid attribute.");

	}

	/**
	 * Delete a post
	 * @param sessionId
	 * 			- Identifier of the session to validate the User logon
	 * @param postId
	 * 			- Identifier of the post will be deleted 
	 * @throws Exception
	 */
	public void deletePost(String postId) {
		if(posts.containsKey(postId)){
			mediasOfPosts.remove(postId);
			commentsOfPosts.remove(postId);
			posts.remove(postId);
		}
		
		
	}
	
	public int getNumberOfPosts() {
		return posts.size();
	}
	


	//Media operations
	/**
	 * Attaches a sound
	 * @param sessionID
	 * 			- Identifier of the session to validate the User logon
	 * @param postID
	 * 			- Identifier of the post that will be inserted audio
	 * @param description
	 * 			- Sound's description
	 * @param data
	 * 			- Data's sound
	 * @return soundId
	 *          - Identifier of the sound
	 * @throws Exception
	 */
	public String attachSound(String postID,
			String description, String data) throws Exception {
				
		if(!mediasOfPosts.containsKey(postID))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postID).attachSound(postID, description, data);
	}

	/**
	 * Attaches a movie
	 * @param sessionID
	 * 			- Identifier of the session to validate the User logon
	 * @param postID
	 * 			- Identifier of the post that will be inserted sound
	 * @param description
	 * 			- Movie's description
	 * @param data
	 * 			- Data's movie
	 * @return moviedId
	 *          - Identifier of the movie
	 * @throws Exception
	 */
	public String attachMovie(String postID,
			String description, String data) throws Exception {
		if(!mediasOfPosts.containsKey(postID))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postID).attachMovie(postID, description, data);
	}


	/**
	 * Attaches a picture
	 * @param sessionID
	 * 			- Identifier of the session to validate the User logon
	 * @param postID
	 * 			- Identifier of the post that will be inserted picture
	 * @param description
	 * 			- Picture's description
	 * @param data
	 * 			- Data's picture
	 * @return pictureId
	 *          - Identifier of the picture
	 * @throws Exception
	 */
	public String attachPicture(String postID,
			String description, String data) throws Exception {
		if(!mediasOfPosts.containsKey(postID))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postID).attachPicture(postID, description, data);
	}
	
	/**
	 * Delete a movie
	 * @param sessionId
	 * 			- Identifier of the session to validate the User logon
	 * @param movieId
	 * 			- Identifier of the movie will be deleted
	 */
	public void deleteMovie(String postId, String movieId) {
		if(mediasOfPosts.containsKey(postId))
			mediasOfPosts.get(postId).deleteMovie(movieId);
	}
	
	/**
	 * Delete a sound
	 * @param sessionId
	 * 			- Identifier of the session to validate the User logon
	 * @param soundId
	 * 			- Identifier of the sound will be deleted
	 */
	public void deleteSound(String postId, String soundId) {
		if(mediasOfPosts.containsKey(postId))
			mediasOfPosts.get(postId).deleteSound(soundId);
		
	}

	/**
	 * Delete a picture
	 * @param sessionId
	 * 			- Identifier of the session to validate the User logon
	 * @param pictureId
	 * 			- Identifier of the picture will be deleted
	 */
	public void deletePicture(String postId, String pictureId) {
		if(mediasOfPosts.containsKey(postId))
			mediasOfPosts.get(postId).deletePicture(pictureId);

	}


	/**
	 * Returns the number of sounds from post
	 * @param postId
	 * 			- Identifier of the post sounds to be counted
	 * @return number of sounds
	 * @throws Exception
	 */
	public int getNumberOfSoundsOfPost(String postId) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getNumberOfSounds();
	}

	/**
	 * Returns the number of pictures from post
	 * @param postId
	 * 			- Identifier of the post pictures to be counted
	 * @return number of pictures
	 * @throws Exception
	 */
	public int getNumberOfPicturesOfPost(String postId) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getNumberOfPictures();
	}
	
	/**
	 * Returns the number of movies from post
	 * @param postId
	 * 			- Identifier of the post movies to be counted
	 * @return number of movies
	 * @throws Exception
	 */
	public int getNumberOfMoviesOfPost(String postId) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getNumberOfMovies();
		
	}
	
	/**
	 * Capturing the sound of the post with the index passed as parameter
	 * @param postId
	 * 			- Identifier of the post which will capture the sound
	 * @param index
	 * 			- Sound's index
	 * @return soundId
	 * @throws Exception
	 */
	public String getSound(String postId, int index) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getSound(index);
	}
	
	/**
	 * Capturing the movie of the post with the index passed as parameter
	 * @param postId
	 * 			- Identifier of the post which will capture the movie
	 * @param index
	 * 			- Movie's index
	 * @return movieId
	 * @throws Exception
	 */
	public String getMovie(String postId, int index) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getMovie(index);
	}
	
	/**
	 * Capturing the picture of the post with the index passed as parameter
	 * @param postId
	 * 			- Identifier of the post which will capture the picture
	 * @param index
	 * 			- Picture's index
	 * @return pictureId
	 * @throws Exception
	 */
	public String getPicture(String postId, int index) throws Exception {
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid Post id");
		return mediasOfPosts.get(postId).getPicture(index);

	}

	
	/**
	 * Returns data of sound
	 * @param soundId
	 * @return data of sound
	 * @throws Exception 
	 */
	public String getSoundData(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getSoundData(mediaId);
	}
	
	/**
	 * Returns description of sound
	 * @param soundId
	 * @return description of sound
	 * @throws Exception 
	 */
	public String getSoundDescription(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getSoundDescription(mediaId);
	}
	
	/**
	 * Returns data of picture
	 * @param picture Id
	 * @return data of picture
	 * @throws Exception 
	 */
	public String getPictureData(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getPictureData(mediaId);
	}
	
	/**
	 * Returns description of picture
	 * @param pictureId
	 * @return description of picture
	 * @throws Exception 
	 */
	public String getPictureDescription(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getPictureDescription(mediaId);
	}
	
	/**
	 * Returns data of movie
	 * @param movie Id
	 * @return data of movie
	 * @throws Exception 
	 */
	public String getMovieData(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getMovieData(mediaId);
	}
	
	/**
	 * Returns description of movie
	 * @param movieId
	 * @return description of movie
	 * @throws Exception 
	 */
	public String getMovieDescription(String postId, String mediaId) throws Exception{
		if(!mediasOfPosts.containsKey(postId))
			throw new Exception("Invalid post id");
		return mediasOfPosts.get(postId).getMovieDescription(mediaId);
	}

	//Comment Operations
	/**
	 * Add a comment
	 * @param postId
	 * 			- identifier of the post which is inserted into the comment
	 * @param comment
	 * 			- Text's comment
	 * @return
	 * @throws Exception
	 */
	public String addComment(String postId, String comment, String login) throws Exception {
		if(!commentsOfPosts.containsKey(postId)){
			throw new Exception("Invalid post id");
		}
		return commentsOfPosts.get(postId).addComment(postId, comment, login);
		
	}
	
	/**
	 * Capturing the post with the index passed as parameter
	 * @param blogId
	 * 			- Identifier of the blog which will capture the post
	 * @param index
	 * 			- Post's index
	 * @return postId
	 */
	public String getPost(int index){
		return posts.get(index).getId();
	}

	

	/**
	 * Returns the number of comments of post
	 * @param postId
	 * 			- Identifier of the post which will capture the number of comments
	 * @return number of posts
	 * @throws Exception
	 */
	public int getNumberOfComments(String postId) throws Exception {
		
		if(!commentsOfPosts.containsKey(postId))
			throw new Exception("Invalid post id.");
					
		return commentsOfPosts.get(postId).getNumberOfComments(postId); 
	}

	
	/**
	 * Capturing the comment with the index passed as parameter
	 * @param postId
	 * 			- Identifier of the post which will capture the comment
	 * @param index
	 * 			- comment's index
	 * @return commentId
	 */
	public String getComment(String postId, int index) throws Exception {
		if(!commentsOfPosts.containsKey(postId))
			throw new Exception("Invalid post id.");
					
		return commentsOfPosts.get(postId).getComment(postId, index);
	}
	
	/**
	 * Retrieves the comment's text passed as parameter
	 * @param commentId
	 * 			- identifier of the comment that the text will be recovered
	 * @return comment's text
	 * @throws Exception
	 */
	public String getCommentText(String postId, String commentId) throws Exception {
		if(!commentsOfPosts.containsKey(postId))
			throw new Exception("Invalid post id.");
					
		return commentsOfPosts.get(postId).getCommentContent(commentId);
	}

	/**
	 * Retrieves the comment's author passed as parameter
	 * @param commentId
	 * 			- identifier of the comment that the author will be recovered
	 * @return comment's author
	 * @throws Exception
	 */
	public String getCommentAuthor(String postId, String commentId) throws Exception {
		if(!commentsOfPosts.containsKey(postId))
			throw new Exception("Invalid post id.");
					
		return commentsOfPosts.get(postId).getAuthor(commentId);	
		
	}

	public String addSubComment(String postId, String commentId, String text, String login) throws Exception{
		if(commentsOfPosts.containsKey(postId))
			return commentsOfPosts.get(postId).addSubComment(commentId, text, login);
		return "";
	}

	public String getSubComment(String postId, String commentId, int index) throws Exception {
		if(commentsOfPosts.containsKey(postId))
			return commentsOfPosts.get(postId).getSubComment(commentId, index);
		return "";
	}

	public int getNumberOfSubComments(String postId, String commentId) throws Exception{
		if(commentsOfPosts.containsKey(postId))
			return commentsOfPosts.get(postId).getNumberOfSubComments(commentId);
		return 0;
		
	}

	public int getNumberOfAllSubComments(String postId, String commentId) {
		if(commentsOfPosts.containsKey(postId))
			return commentsOfPosts.get(postId).getNumberOfAllSubComments(commentId);
		return 0;
		
	}

	public int getNumberOfCommentsByLogin(String login) {
		int numberOfComments = 0;
		for(Iterator<CommentManager> comments = commentsOfPosts.values().iterator(); comments.hasNext();)
			numberOfComments += comments.next().getNumberOfCommentsByLogin(login);
		return numberOfComments;
	}


	public void save(){
		DBFacade.getInstance().savePosts(posts.values());
	}

	//Private methods
	private String getNewPostId() {
		return String.valueOf(DBFacade.getInstance().getLastPostId());
	}



}
